--[[
	Lysidia's Party XP

	This is the main program segment.
]]

--------------------------------------------------------------------------------------------------
-- Actual Program Functions
--------------------------------------------------------------------------------------------------
-- Function to return "tooltip" information.
function LPXP_SetTooltipText(tooltip)
	LPXP_SendXPUpdate();

	tooltip:AddLine(LPXP_TEXT, 1.0, 1.0, 1.0);
	tooltip:AddLine(" ");

	local tooltipText	= "";
	local player		= UnitName("player");
	local playerPet		= UnitName("pet");
	local myCur		= LPXP_XPTable[player]["current"];
	local myMax		= LPXP_XPTable[player]["maximum"];

	-- Show the player's XP stats
	-- If we are set to show the remaining XP to level, then calculate the remaining XP, otherwise show the current XP.
	if (LPXP_Config.ShowRemaining == true) then
		tooltip:AddDoubleLine(player, format(LPXP_XPTEXT, (myMax - myCur), myMax), 0.8, 0.8, 1.0);
	else
		tooltip:AddDoubleLine(player, format(LPXP_XPTEXT, myCur, myMax), 0.8, 0.8, 1.0);
	end

	-- Show the player's pet's XP stats if pet XP stats are wanted displayed.
	if ((LPXP_Config.ShowPartyPets == true) and (playerPet ~= nil)) then
		myCur = LPXP_XPTable[playerPet]["current"];
		myMax = LPXP_XPTable[playerPet]["maximum"];

		-- Warlock pets do not have XP so their values show up as 0, so we don't show XP for them
		-- Hunter pets do, so we show their stats.
		if (myMax == 0) then
			tooltip:AddDoubleLine("- "..playerPet, "N/A", 0.6, 0.6, 1.0);
		else
			-- If we are set to show the remaining XP to level, then calculate the remaining XP, otherwise show the current XP.
			if (LPXP_Config.ShowRemaining == true) then
				tooltip:AddDoubleLine("- "..playerPet, format(LPXP_XPTEXT, (myMax - myCur), myMax), 0.6, 0.6, 1.0);
			else
				tooltip:AddDoubleLine("- "..playerPet, format(LPXP_XPTEXT, myCur, myMax), 0.6, 0.6, 1.0);
			end
		end
	end

	-- Iterate through the people in the party
	for index = 1, GetNumGroupMembers() do
		-- Add a line break between each player group
		tooltip:AddLine(" ");

		-- If this party member exists, then deal with them
		if (UnitName("party"..index) ~= nil) then
			-- Set the playerName and playerPetName as we re-use this a lot through here.
			local playerName	= UnitName("party"..index);
			local playerPetName	= UnitName("partypet"..index);

			if (LPXP_XPTable[playerName] ~= nil) then
				myCur = LPXP_XPTable[playerName]["current"];
				myMax = LPXP_XPTable[playerName]["maximum"];

				-- Show this party member's XP stats
				-- If we are set to show the remaining XP to level, then calculate the remaining XP, otherwise show the current XP.
				if (LPXP_Config.ShowRemaining == true) then
					tooltip:AddDoubleLine(playerName, format(LPXP_XPTEXT, (myMax - myCur), myMax), 0.8, 0.8, 1.0);
				else
					tooltip:AddDoubleLine(playerName, format(LPXP_XPTEXT, myCur, myMax), 0.8, 0.8, 1.0);
				end

				-- Show this party member's pet's XP stats if pet XP stats are wanted displayed
				if ((LPXP_Config.ShowPartyPets == true) and (playerPetName ~= nil)) then
					myCur = LPXP_XPTable[playerPetName]["current"];
					myMax = LPXP_XPTable[playerPetName]["maximum"];

					-- Warlock pets do not have XP so their values show up as 0, so we don't show XP for them
					-- Hunter pets do, so we show their stats.
					if (myMax == 0) then
						tooltip:AddDoubleLine("- "..playerPetName, "N/A", 0.6, 0.6, 1.0);
					else
						-- If we are set to show the remaining XP to level, then calculate the remaining XP, otherwise show the current XP.
						if (LPXP_Config.ShowRemaining == true) then
							tooltip:AddDoubleLine("- "..playerPetName, format(LPXP_XPTEXT, (myMax - myCur), myMax), 0.6, 0.6, 1.0);
						else
							tooltip:AddDoubleLine("- "..playerPetName, format(LPXP_XPTEXT, myCur, myMax), 0.6, 0.6, 1.0);
						end
					end
				end
			else
				tooltip:AddDoubleLine(playerName, UNKNOWN, 0.8, 0.8, 1.0);
				if ((LPXP_Config.ShowPartyPets == true) and (playerPetName ~= nil)) then
					tooltip:AddDoubleLine("- "..playerPetName, UNKNOWN, 0.6, 0.6, 1.0);
				end
			end
		end
	end

	return tooltipText;
end

function LPXP_SendXPUpdate()
	-- Get player XP details
	local myName	= UnitName("player");
	local XPCur	= UnitXP("player");
	local XPMax	= UnitXPMax("player");

	-- If this is the first run through, set up the player variable
	if (LPXP_XPTable[myName] == nil) then
		LPXP_XPTable[myName] = {};
	end

	-- Set the actual data variables, these will be used to display the data later
	LPXP_XPTable[myName]["current"]	= XPCur;
	LPXP_XPTable[myName]["maximum"]	= XPMax;
	LPXP_XPTable[myName]["type"]	= 1;

	-- Send the information to others in the party who run this addon via the hidden addon channel
	SendAddonMessage(LPXP_ID, format(LPXP_ADDONMSG, myName, XPCur, XPMax), "PARTY");

	-- 
	local petName	= UnitName("pet");
	local PetXPCur, PetXPMax = GetPetExperience();
	-- Check to see if there is a max XP for the pet, either their will be, and this is a hunter pet, or their won't be and the pet is a warlock pet or no pet at all.
	if (PetXPMax ~= 0) then
		-- If this is the first run through, set up the player's pet variable
		if (LPXP_XPTable[petName] == nil) then
			LPXP_XPTable[petName] = {};
		end

		-- Set the actual data variables, these will be used to display the data later
		LPXP_XPTable[petName]["current"]	= PetXPCur;
		LPXP_XPTable[petName]["maximum"]	= PetXPMax;

		-- Send the information to others in the party who run this addon via the hidden addon channel
		SendAddonMessage(LPXP_ID, format(LPXP_ADDONMSG, petName, PetXPCur, PetXPMax), "PARTY");

	-- Now we check to see if there is a pet, as if there is, this is a warlock pet as it has no max XP.
	elseif (petName ~= nil) then
		-- If this is the first run through, set up the player's pet variable
		if (LPXP_XPTable[petName] == nil) then
			LPXP_XPTable[petName] = {};
		end

		-- Set the actual data variables, these will be used to display the data later
		LPXP_XPTable[petName]["current"]	= 0;
		LPXP_XPTable[petName]["maximum"]	= 0;
		LPXP_XPTable[petName]["type"]		= 2;

		-- Send the information to others in the party who run this addon via the hidden addon channel
		SendAddonMessage(LPXP_ID, format(LPXP_ADDONMSG, petName, 0, 0), "PARTY");
	end
end

function LPXP_ReceiveXPUpdate(message, player)
	-- Split out the various text segments for use
	local _, _, unitName, XPCur, XPMax = string.find(message, "(.*)#(.*)#(.*)");

	-- Check to make sure we have valid data as a string match that fails will return nil
	if (unitName ~= nil) then
		-- Define the data block for this sender if unknown
		if (LPXP_XPTable[unitName] == nil) then
			LPXP_XPTable[unitName] = {};
		end

		-- Set the actual data variables, these will be used to display the data later
		LPXP_XPTable[unitName]["current"]	= XPCur;
		LPXP_XPTable[unitName]["maximum"]	= XPMax;
	end
end

function LPXP_Shared_Split(toCut, separator)
	local splitted = {};
	local i = 0;
	local regEx = "([^" .. separator .. "]*)" .. separator .. "?";

	for item in string.gmatch(toCut .. separator, regEx) do
		i = i + 1;
		splitted[i] = string.gsub(item, "^%s*(.-)%s*$", "%1") or '';
	end
	splitted[i] = nil;
	return splitted;
end

--------------------------------------------------------------------------------------------------
-- Program functions below
--------------------------------------------------------------------------------------------------
function LPXP_OnLoad(frame)
	if (LPXP_Config == nil) then
		LPXP_Config = {};
	end

	if (LPXP_Config.ShowRemaining == nil) then
		LPXP_Config.ShowRemaining = true;
	end

	if (LPXP_Config.ShowPartyPets == nil) then
		LPXP_Config.ShowPartyPets = true;
	end

	-- Register for the ADDON_LOADED event...
	frame:RegisterEvent("ADDON_LOADED");
	
	-- This event is the special addon hidden channel event, we listen to this to share data between players running this addon
	frame:RegisterEvent("CHAT_MSG_ADDON");

	-- These are the various events that trigger an addon update message
	frame:RegisterEvent("PLAYER_ENTERING_WORLD");
	frame:RegisterEvent("UNIT_PET_EXPERIENCE");
	frame:RegisterEvent("PLAYER_XP_UPDATE");
	frame:RegisterEvent("PARTY_MEMBERS_CHANGED");

end

-- Function: Main Event function handler
function LPXP_OnEvent(frame, event, ...)
	-- If the event is that of an addon chat message, handle the inbound message
	if ((event == "ADDON_LOADED") and (select(1, ...) == "LysPartyXP")) then
		DEFAULT_CHAT_FRAME:AddMessage(LPXP_LOADSTRING, 0.2, 1.0, 0.2);
		return;

	elseif (event == "CHAT_MSG_ADDON") then
		-- Only deal with the message if it is from another copy of this addon, and not from this player.
		if ((select(1, ...) == LPXP_ID) and (UnitName("player") ~= select(4, ...))) then
			LPXP_ReceiveXPUpdate(select(2, ...), select(4, ...));
		end
		return;
	end

	-- If we got here, then we need to process other updates.
	LPXP_SendXPUpdate();
end

